<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="玖忆;文鹤;博客">
    
    <meta name="author" content="meteor">
    <!-- preconnect -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    
    
    <!--- Seo Part-->
    
    <link rel="canonical" href="https://wait-you.github.io/2023/06/06/java并发编程/"/>
    <meta name="robots" content="index,follow">
    <meta name="googlebot" content="index,follow">
    <meta name="revisit-after" content="1 days">
    
        <meta name="description" content="# JAVA 并发编程 # 进程与线程 # 进程  程序由指令和数据组成，但这些指令要运行，数据要读写，就必须将指令加载至 CPU，数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 当一个程序被运行，从磁盘加载这个程序的代码至内存，这时就开启了一个进程。 进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程（例如记事本、画图、浏">
<meta property="og:type" content="article">
<meta property="og:title" content="JAVA并发编程">
<meta property="og:url" content="https://wait-you.github.io/2023/06/06/JAVA%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/index.html">
<meta property="og:site_name" content="玖忆">
<meta property="og:description" content="# JAVA 并发编程 # 进程与线程 # 进程  程序由指令和数据组成，但这些指令要运行，数据要读写，就必须将指令加载至 CPU，数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 当一个程序被运行，从磁盘加载这个程序的代码至内存，这时就开启了一个进程。 进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程（例如记事本、画图、浏">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://tuchuang.wenhe9.cn/image-20220310201758451.png">
<meta property="og:image" content="http://tuchuang.wenhe9.cn/image-20220310220616173.png">
<meta property="og:image" content="http://tuchuang.wenhe9.cn/image-20220310221423039.png">
<meta property="article:published_time" content="2023-06-06T00:42:26.000Z">
<meta property="article:modified_time" content="2023-06-05T08:42:55.121Z">
<meta property="article:author" content="meteor">
<meta property="article:tag" content="java">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://tuchuang.wenhe9.cn/image-20220310201758451.png">
    
    
    <!--- Icon Part-->
    <link rel="icon" type="image/png" href="/images/wenhe.png" sizes="192x192">
    <link rel="apple-touch-icon" sizes="180x180" href="/images/wenhe.png">
    <meta name="theme-color" content="#f1404b">
    <link rel="shortcut icon" href="/images/wenhe.png">
    <!--- Page Info-->
    
    <title>
        
            JAVA并发编程 -
        
        玖忆
    </title>
    
<link rel="stylesheet" href="/css/style.css">

    
<link rel="stylesheet" href="/assets/fonts.css">

    <!--- Font Part-->
    
    
    
    

    <!--- Inject Part-->
    
    <script id="hexo-configurations">
    let Global = window.Global || {};
    Global.hexo_config = {"hostname":"wait-you.github.io","root":"/","language":"zh-CN"};
    Global.theme_config = {"articles":{"style":{"font_size":"16px","line_height":1.5,"image_border_radius":"14px","image_alignment":"center","image_caption":false,"link_icon":true},"word_count":{"enable":true,"count":true,"min2read":true},"author_label":{"enable":true,"auto":false,"list":[]},"code_block":{"copy":true,"style":"mac","font":{"enable":false,"family":null,"url":null}},"toc":{"enable":true,"max_depth":3,"number":false,"expand":true,"init_open":true},"copyright":true,"lazyload":true,"recommendation":{"enable":false,"title":"推荐阅读","limit":3,"placeholder":"http://tuchuang.wenhe9.cn/default-bg.jpg","skip_dirs":[]}},"colors":{"primary":"#f1404b","secondary":null},"global":{"fonts":{"chinese":{"enable":false,"family":null,"url":null},"english":{"enable":false,"family":null,"url":null}},"content_max_width":"1000px","sidebar_width":"210px","hover":{"shadow":true,"scale":false},"scroll_progress":{"bar":true,"percentage":true},"busuanzi_counter":{"enable":true,"site_pv":true,"site_uv":true,"post_pv":true},"pjax":true,"open_graph":true,"google_analytics":{"enable":false,"id":null}},"home_banner":{"enable":true,"style":"static","image":{"light":"http://tuchuang.wenhe9.cn/default-bg.jpg","dark":"http://tuchuang.wenhe9.cn/default-bg.jpg"},"title":"玖忆","subtitle":{"text":["我本微末凡尘、可也心向天空"],"hitokoto":{"enable":false,"api":"https://v1.hitokoto.cn"},"typing_speed":100,"backing_speed":80,"starting_delay":500,"backing_delay":1500,"loop":true,"smart_backspace":true},"text_color":{"light":"#fff","dark":"#d1d1b6"},"text_style":{"title_size":"2.8rem","subtitle_size":"1.5rem","line_height":1.2},"custom_font":{"enable":false,"family":null,"url":null},"social_links":{"enable":true,"links":{"github":"https://gitee.com/du-jinliang","instagram":null,"zhihu":null,"twitter":null,"email":"dujinliang9@163.com"}}},"plugins":{"feed":{"enable":false},"aplayer":{"enable":false,"type":"fixed","audios":[{"name":null,"artist":null,"url":null,"cover":null}]},"mermaid":{"enable":false,"version":"9.3.0"}},"version":"2.1.4","navbar":{"auto_hide":true,"color":{"left":"#f78736","right":"#367df7","transparency":35},"links":{"Home":{"path":"/","icon":"fa-regular fa-house"}},"search":{"enable":false,"preload":true}},"page_templates":{"friends_column":2,"tags_style":"blur"},"home":{"sidebar":{"enable":true,"position":"left","first_item":"menu","announcement":null,"links":null},"article_date_format":"auto","categories":{"enable":true,"limit":3},"tags":{"enable":true,"limit":3}}};
    Global.language_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 个月前","year":"%s 年前"};
    Global.data_config = {"masonry":false};
  </script>
    
    <!--- Fontawesome Part-->
    
<link rel="stylesheet" href="/fontawesome/fontawesome.min.css">

    
<link rel="stylesheet" href="/fontawesome/brands.min.css">

    
<link rel="stylesheet" href="/fontawesome/solid.min.css">

    
<link rel="stylesheet" href="/fontawesome/regular.min.css">

    
    
    
    
<meta name="generator" content="Hexo 6.3.0"></head>


<body>
<div class="progress-bar-container">
    
        <span class="scroll-progress-bar"></span>
    

    
        <span class="pjax-progress-bar"></span>
        <span class="pjax-progress-icon">
            <i class="fa-solid fa-circle-notch fa-spin"></i>
        </span>
    
</div>


<main class="page-container">

    

    <div class="main-content-container">

        <div class="main-content-header">
            <header class="navbar-container">
    
    <div class="navbar-content">
        <div class="left">
            
            <a class="logo-title" href="/">
                
                玖忆
                
            </a>
        </div>

        <div class="right">
            <!-- PC -->
            <div class="desktop">
                <ul class="navbar-list">
                    
                        
                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class="" 
                                    href="/"  >
                                    
                                        
                                            <i class="fa-regular fa-house"></i>
                                        
                                        首页
                                    
                                </a>
                                <!-- Submenu -->
                                
                            </li>
                    
                    
                </ul>
            </div>
            <!-- Mobile -->
            <div class="mobile">
                
                <div class="icon-item navbar-bar">
                    <div class="navbar-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- Mobile drawer -->
    <div class="navbar-drawer">
        <ul class="drawer-navbar-list">
            
                
                    <li class="drawer-navbar-item flex-center">
                        <a class="" 
                        href="/"  >
                             
                                
                                    <i class="fa-regular fa-house"></i>
                                
                                首页
                            
                        </a>
                    </li>
                    <!-- Submenu -->
                    
            

        </ul>
    </div>

    <div class="window-mask"></div>

</header>


        </div>

        <div class="main-content-body">

            

            <div class="main-content">

                
                    <div class="fade-in-down-animation">
    <div class="post-page-container">
        <div class="article-content-container">

            
            
                <div class="article-title">
                    <h1 class="article-title-regular">JAVA并发编程</h1>
                </div>
            
                
            

            
                <div class="article-header">
                    <div class="avatar">
                        <img src="/images/wenhe.png">
                    </div>
                    <div class="info">
                        <div class="author">
                            <span class="name">meteor</span>
                            
                                <span class="author-label">Lv3</span>
                            
                        </div>
                        <div class="meta-info">
                            <div class="article-meta-info">
    <span class="article-date article-meta-item">
        <i class="fa-regular fa-pen-fancy"></i>&nbsp;
        <span class="desktop">2023-06-05 16:42:26</span>
        <span class="mobile">2023-06-05 16:42</span>
        <span class="hover-info">创建</span>
    </span>
    
        <span class="article-date article-meta-item">
            <i class="fa-regular fa-wrench"></i>&nbsp;
            <span class="desktop">2023-06-05 00:42:55</span>
            <span class="mobile">2023-06-05 00:42</span>
            <span class="hover-info">更新</span>
        </span>
    

    
        <span class="article-categories article-meta-item">
            <i class="fa-regular fa-folders"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/categories/Java/">Java</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fa-regular fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/java/">java</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
    
    
        <span class="article-pv article-meta-item">
            <i class="fa-regular fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

                        </div>
                    </div>
                </div>
            

            <div class="article-content markdown-body">
                <h1 id="java并发编程"><a class="markdownIt-Anchor" href="#java并发编程">#</a> JAVA 并发编程</h1>
<h2 id="进程与线程"><a class="markdownIt-Anchor" href="#进程与线程">#</a> 进程与线程</h2>
<h3 id="进程"><a class="markdownIt-Anchor" href="#进程">#</a> 进程</h3>
<ul>
<li>程序由指令和数据组成，但这些指令要运行，数据要读写，就必须将指令加载至 CPU，数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的</li>
<li>当一个程序被运行，从磁盘加载这个程序的代码至内存，这时就开启了一个进程。</li>
<li>进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程（例如记事本、画图、浏览器等），也有的程序只能启动一个实例进程（例如网易云音乐、360 安全卫士等）</li>
</ul>
<h3 id="线程"><a class="markdownIt-Anchor" href="#线程">#</a> 线程</h3>
<ul>
<li>一个进程内可以分为一到多个线程</li>
<li>一个进程就是一个指令流，将指令流中的一条条指令以一定的顺序交给 CPU 执行</li>
<li>Java 中，线程作为最小的调度单位，进程作为资源分配的最小单位。在 windows 中进程是不活动的，只是作为线程的容器</li>
</ul>
<h3 id="二者对比"><a class="markdownIt-Anchor" href="#二者对比">#</a> 二者对比</h3>
<ul>
<li>进程基本上是相互独立的，而线程存在于进程内，是进程的一个子集</li>
<li>进程拥有共享的资源，如内存空间等，供其内部的线程共享</li>
<li>进程间通信较为复杂
<ul>
<li>同一台计算机的进程通信称为 IPC（Inter-process commucation）</li>
<li>不同计算机之间的进程通信，需要通过网络，并遵守共同的协议，例如 HTTP</li>
</ul>
</li>
<li>线程通信相对简单，因为他们共享进程内的内存，一个例子是多个线程可以访问同一个共享变量</li>
<li>线程更轻量，线程上下文切换成本一般要比进程上下文切换低</li>
</ul>
<h3 id="并行与并发"><a class="markdownIt-Anchor" href="#并行与并发">#</a> 并行与并发</h3>
<p>单核 cpu 下，线程实际还是串行执行的。操作系统有一个组件叫做任务调度器，将 cpu 的时间片（windows 下时间片最小约为 15 毫秒）分给不同的线程使用，只是由于 cpu 在线程间（时间片很短）的切换非常快，人类感觉是同时运行的。总结一句话就是： <code>微观串行，宏观并行</code></p>
<p>一般会将这种线程轮流使用 cpu 的做法称为并发，concurrent</p>
<p>多核 cpu 下，每个核（core）都可以调度运行线程，这时候线程是可以并行的</p>
<ul>
<li>并发（concurrent）是同一时间应对（dealing with）多件事情的能力</li>
<li>并行（parallel）是同一时间动手做（doing）多件事情的能力</li>
</ul>
<h3 id="应用"><a class="markdownIt-Anchor" href="#应用">#</a> 应用</h3>
<h4 id="应用之异步调用案例1"><a class="markdownIt-Anchor" href="#应用之异步调用案例1">#</a> 应用之异步调用（案例 1）</h4>
<p>从方法调用的角度来讲，如果</p>
<ul>
<li>需要等待结果返回，才能继续运行就是同步</li>
<li>不需要等待结果返回，就能继续运行的就是异步</li>
</ul>
<p>注意：同步在多线程中还有另外一层意思，是让多个线程步调一致</p>
<h5 id="1设计"><a class="markdownIt-Anchor" href="#1设计">#</a> 1) 设计</h5>
<p>多线程可以让方法执行变为异步的（即不要干巴巴的等着）比如说读取磁盘文件时，假设读取操作花费了 5 秒钟，如果没有线程调度机制，这 5 秒调用者什么都做不了，其他代码都得暂停…</p>
<h5 id="2结论"><a class="markdownIt-Anchor" href="#2结论">#</a> 2) 结论</h5>
<ul>
<li>比如在项目中，视频文件需要转换格式等操作比较费时，这时开一个新线程处理视频转换，避免阻塞主线程</li>
<li>tocmat 的异步 servlet 也是类似的目的，让用户线程处理耗时教程的操作，避免阻塞 tomcat 的工作线程</li>
<li>ui 程序中，开线程进行其他操作，避免阻塞 ui 线程</li>
</ul>
<h4 id="应用之提高效率案例2"><a class="markdownIt-Anchor" href="#应用之提高效率案例2">#</a> 应用之提高效率（案例 2）</h4>
<p>充分利用多核 cpu 的优势，提高运行效率。想想下面的场景，执行三个运算，最后将计算结果汇总</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">计算1 花费 10ms</span><br><span class="line"></span><br><span class="line">计算2 花费 11ms</span><br><span class="line"></span><br><span class="line">计算3 花费 9ms</span><br><span class="line"></span><br><span class="line">汇总需要 1ms</span><br></pre></td></tr></table></figure></div>
<ul>
<li>如果是串行执行，那么总共花费的时间是 10 + 11 + 9 + 1 = 31ms</li>
<li>但如果是四核 cpu，各个核心分别使用线程 1 执行计算 1，线程 2 执行计算 2，线程 3 执行计算 3，那么三个线程是并行的，花费时间只取决于最长的那个线程运行的时间，即 11ms 最后汇总时间只会花费 12ms</li>
</ul>
<blockquote>
<p><strong>注意</strong></p>
<p>需要在多核 cpu 才能提高效率，单核仍然是轮流运行</p>
</blockquote>
<h5 id="1设计-2"><a class="markdownIt-Anchor" href="#1设计-2">#</a> 1) 设计</h5>
<h5 id="2结论-2"><a class="markdownIt-Anchor" href="#2结论-2">#</a> 2) 结论</h5>
<ol>
<li>单核 cpu 下，多线程不能实际提高程序运行效率，只是为了能够在不同的任务之间切换，不同线程轮流使用 cpu，不至于一个线程总占用 cpu，别的线程没法干活</li>
<li>多核 cpu 可以并行跑多个线程，但能否提高程序运行效率还是要分情况的
<ul>
<li>有些任务，经过精心设计，将任务拆分，并行执行，当然可以提高程序的运行效率。但不是所有计算任务都能拆分（参考后文的【阿姆达尔定律】）</li>
<li>也不是所有任务都需要拆分，任务的目的如果不同，谈拆分和效率没啥意义</li>
</ul>
</li>
<li>IO 操作不占用 cpu，只是我们一般拷贝文件使用的是【阻塞 IO】，这时相当于线程虽然不使用 cpu，但需要一直等待 IO 结束，没能充分利用线程，所有才有后面的【非阻塞 IO】和【异步 IO】优化</li>
</ol>
<h2 id="java线程"><a class="markdownIt-Anchor" href="#java线程">#</a> Java 线程</h2>
<h3 id="创建和运行线程"><a class="markdownIt-Anchor" href="#创建和运行线程">#</a> 创建和运行线程</h3>
<h4 id="方法一直接使用thread"><a class="markdownIt-Anchor" href="#方法一直接使用thread">#</a> 方法一，直接使用 Thread</h4>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Thread</span> <span class="variable">t</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>()&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="comment">//要执行的任务</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">//启动线程</span></span><br><span class="line">t.start();</span><br></pre></td></tr></table></figure></div>
<p>例如：</p>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造方法的参数是给线程指定的名字，推荐</span></span><br><span class="line"><span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>()&#123;</span><br><span class="line"> 	<span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="comment">//要执行的任务</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//启动线程</span></span><br><span class="line">t1.start();</span><br></pre></td></tr></table></figure></div>
<h4 id="方法二使用runnable配合thread"><a class="markdownIt-Anchor" href="#方法二使用runnable配合thread">#</a> 方法二，使用 Runnable 配合 Thread</h4>
<p>把【线程】和【任务】（要执行的代码）分开</p>
<ul>
<li>Thread 代表线程</li>
<li>Runnable 可运行的任务（线程要执行的代码）</li>
</ul>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Runnable</span> <span class="variable">runnable</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Runnable</span>()&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="comment">//要执行的任务</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//创建线程对象</span></span><br><span class="line"><span class="comment">//参数1 是 任务对象 ； 参数2 是 线程名字 </span></span><br><span class="line"><span class="type">Thread</span> <span class="variable">t</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(runnable, <span class="string">&quot;t2&quot;</span>);</span><br><span class="line"><span class="comment">//启动线程</span></span><br><span class="line">t.start();</span><br></pre></td></tr></table></figure></div>
<h4 id="原理之thread和runnable的关系"><a class="markdownIt-Anchor" href="#原理之thread和runnable的关系">#</a> 原理之 Thread 和 Runnable 的关系</h4>
<p><strong>小结</strong></p>
<ul>
<li>方法 1 是把线程和任务合并在了一起，方法 2 是把线程和任务分开了</li>
<li>用 Runnable 更容易与线程池等高级 API 配合</li>
<li>用 Runnable 让任务脱离了 Thread 继承体系，更灵活</li>
</ul>
<h4 id="方法三futuretask配合thread"><a class="markdownIt-Anchor" href="#方法三futuretask配合thread">#</a> 方法三，FutureTask 配合 Thread</h4>
<p>FutureTask 能够接收 Callable 类型的参数，用来处理有返回结果的情况</p>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//创建任务对象</span></span><br><span class="line">FutureTask&lt;Integer&gt; task3 = <span class="keyword">new</span> <span class="title class_">FutureTask</span>&lt;&gt;(<span class="keyword">new</span> <span class="title class_">Callable</span>&lt;Integer&gt;() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        log.info(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">100</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line">task3 = <span class="keyword">new</span> <span class="title class_">FutureTask</span>&lt;Integer&gt;(() -&gt; &#123;</span><br><span class="line">    log.info(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">100</span>;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//参数1 是 任务对象； 参数2 是 线程名字</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Thread</span>(task3, <span class="string">&quot;t3&quot;</span>).start();</span><br><span class="line"></span><br><span class="line"><span class="comment">//主线程阻塞，同步等待task执行完毕的结果</span></span><br><span class="line"><span class="type">Integer</span> <span class="variable">result</span> <span class="operator">=</span> task3.get();</span><br><span class="line">log.info(<span class="string">&quot;结果是:&#123;&#125;&quot;</span>, result);</span><br></pre></td></tr></table></figure></div>
<p>​</p>
<h3 id="查看进程的方法"><a class="markdownIt-Anchor" href="#查看进程的方法">#</a> 查看进程的方法</h3>
<h4 id="windows"><a class="markdownIt-Anchor" href="#windows">#</a> windows</h4>
<ul>
<li>任务管理器可以查看进程数和线程数，也可以用来杀死进程</li>
<li>tasklist 查看进程</li>
<li>taskkill 杀死进程</li>
</ul>
<h4 id="linux"><a class="markdownIt-Anchor" href="#linux">#</a> linux</h4>
<ul>
<li>ps -ef 查看所有进程</li>
<li>ps -fT -p <pid>查看某个进程（PID）的所有线程</li>
<li>kill 杀死进程</li>
<li>top 按大写 H 切换是否显示进程</li>
<li>top -H -p <PID> 查看某个进程 （PID）的所有线程</li>
</ul>
<h4 id="java"><a class="markdownIt-Anchor" href="#java">#</a> Java</h4>
<ul>
<li>jps 查看所有的 Java 进程</li>
<li>jstack <PID> 查看某个 Java 进程（PID）的所有线程状态</li>
<li>jconsole 来查看某个 Java 进程中线程的运行情况（图形界面）</li>
</ul>
<p>jconsole 远程监控配置</p>
<ul>
<li>
<p>需要以如下方式运行你的 Java 类</p>
<ul>
<li>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><figcaption data-lang="Bash"></figcaption><table><tr><td data-num="1"></td><td><pre><span class="token function">java</span> <span class="token parameter variable">-Djava.rmi.server.hostname</span><span class="token operator">=</span><span class="token variable"><span class="token variable">`</span>ip地址<span class="token variable">`</span></span> <span class="token parameter variable">-Dcom.sun.management.jmxremote</span> <span class="token parameter variable">-Dcom.sun.management.jmxremote.port</span><span class="token operator">=</span><span class="token variable"><span class="token variable">`</span>连接端口<span class="token variable">`</span></span> <span class="token parameter variable">-Dcom.sun.management.jmxremote.sll</span><span class="token operator">=</span><span class="token variable"><span class="token variable">`</span>是否安全连接<span class="token variable">`</span></span> <span class="token parameter variable">-Dcom.sun.management.jmxremote.authenticate</span><span class="token operator">=</span><span class="token variable"><span class="token variable">`</span>是否认证<span class="token variable">`</span></span> java类</pre></td></tr><tr><td data-num="2"></td><td><pre><span class="token operator">&lt;</span><span class="token operator">!</span>--code￼5--<span class="token operator">></span></pre></td></tr></table></figure></div></li>
</ul>
</li>
<li>
<p>可以用 wait 或条件变量达到类似的效果</p>
</li>
<li>
<p>不同的是，后两种条件都需要加锁，并且需要相应的唤醒操作，一般适用于要进行同步的场景</p>
</li>
<li>
<p>sleep 适用于无锁 的同步的场景</p>
</li>
</ul>
<h4 id="两阶段终止模式"><a class="markdownIt-Anchor" href="#两阶段终止模式">#</a> 两阶段终止模式</h4>
<p>Two Phase Termination</p>
<p>在一个线程 T1 中如何 “优雅” 终止线程 T2？这里的【优雅】指的是给 T2 一个料理后事得到机会</p>
<h6 id="1错误思路"><a class="markdownIt-Anchor" href="#1错误思路">#</a> 1. 错误思路</h6>
<ul>
<li>使用线程对象的 stop () 方法终止线程
<ul>
<li>stop 方法会真正杀死线程，如果这时对线程锁住了共享资源，那么当他被杀死后就再也没有机会释放锁，其他线程将永远无法获取锁</li>
</ul>
</li>
<li>使用 System.exit (int) 方法停止线程
<ul>
<li>目的仅是停止一个线程，但这种做法会让整个程序都停止</li>
</ul>
</li>
</ul>
<h6 id="2两阶段终止模式"><a class="markdownIt-Anchor" href="#2两阶段终止模式">#</a> 2. 两阶段终止模式</h6>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://tuchuang.wenhe9.cn/image-20220310201758451.png"
                      alt="image-20220310201758451"
                ></p>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">TwoPhaseTermination</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Thread monitor;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">Logger</span> <span class="variable">logger</span> <span class="operator">=</span> Logger.getLogger(<span class="string">&quot;c.TwoPhaseTermination&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 启动监控线程</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">()</span>&#123;</span><br><span class="line">        monitor = <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">while</span> (<span class="literal">true</span>)&#123;</span><br><span class="line">                <span class="type">Thread</span> <span class="variable">current</span> <span class="operator">=</span> Thread.currentThread();</span><br><span class="line">                <span class="keyword">if</span> (current.isInterrupted())&#123;</span><br><span class="line">                    logger.log(Level.INFO, <span class="string">&quot;料理后事&quot;</span>);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">1000</span>); <span class="comment">//情况1</span></span><br><span class="line">                    logger.log(Level.INFO, <span class="string">&quot;执行监控记录&quot;</span>); <span class="comment">//情况2</span></span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                    <span class="comment">//重新设置打断标记</span></span><br><span class="line">                    current.interrupt();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        monitor.start();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 停止监控线程</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">()</span>&#123;</span><br><span class="line">        monitor.interrupt();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
<h3 id="主线程与守护线程"><a class="markdownIt-Anchor" href="#主线程与守护线程">#</a> 主线程与守护线程</h3>
<p>默认情况下，Java 进程需要等待所有线程都运行结束，才会结束，有一种特殊的线程叫做守护线程（通过 setDdaemon (true) 设置），只要其他非守护线程运行结束了，即使守护线程的代码没有执行完，也会强制结束</p>
<blockquote>
<p>注意：</p>
<ul>
<li>垃圾回收器就是一种守护线程</li>
<li>Tomcat 中的 Acceptor 和 Poller 线程都是守护线程，所以 Tomcat 接收到 shutdown 命令后，不会等待他们处理完当前请求</li>
</ul>
</blockquote>
<h3 id="五种状态"><a class="markdownIt-Anchor" href="#五种状态">#</a> 五种状态</h3>
<p>这是从操作系统的层面来描述的</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://tuchuang.wenhe9.cn/image-20220310220616173.png"
                      alt="image-20220310220616173"
                ></p>
<ul>
<li>【初始状态】仅是语言层面创建了线程对象，还未与操作系统线程关联</li>
<li>【可运行状态】（就绪状态）指该线程已经被创建（与操作系统线程关联），可以由 CPU 调度执行</li>
<li>【运行状态】指获取了 CPU 时间片运行中的状态
<ul>
<li>当 CPU 时间片用完，会从【运行状态】转换至【可运行状态】，会导致线程上下文切换</li>
</ul>
</li>
<li>【阻塞状态】
<ul>
<li>如果调用了阻塞 API，如 BIO 读写文件，这时线程实际不会用到 CPU，会导致线程上下文切换，进入【阻塞状态】</li>
<li>带 BIO 操作完毕，会由操作系统唤醒阻塞的线程，转换至【可运行状态】</li>
<li>与【可运行状态】的区别是，对【阻塞状态】的线程来说只要他们一直不唤醒，调度器就一直不会考虑调度他们</li>
</ul>
</li>
<li>【终止状态】
<ul>
<li>表示线程已经执行完毕，生命周期已经结束，不会再转换为其他状态</li>
</ul>
</li>
</ul>
<h3 id="六种状态"><a class="markdownIt-Anchor" href="#六种状态">#</a> 六种状态</h3>
<p>这是从 Java API 层面来描述的</p>
<p>根据 Thread.State 枚举，分为六种状态</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://tuchuang.wenhe9.cn/image-20220310221423039.png"
                      alt="image-20220310221423039"
                ></p>
<ul>
<li>NEW 线程刚刚被创建，但是还没有调用 start () 方法</li>
<li>RUNNABLE 当调用了 start () 方法之后，注意，Java API 层面的 RUNNABLE 状态涵盖了操作系统层面的【可运行状态】、【运行状态】、【阻塞状态】（由于 BIO 导致的线程阻塞，在 Java 里面无法区分，仍然认为是可运行的）</li>
<li>BLOCKED、WAITING (join)、TIMED_WAITING (sleep) 都是 JAVA API 对【阻塞状态】的细分</li>
<li>TERMINATED 当线程代码运行结束</li>
</ul>
<h3 id="共享模型之管程"><a class="markdownIt-Anchor" href="#共享模型之管程">#</a> 共享模型之管程</h3>
<ul>
<li>共享问题</li>
<li>sychronized</li>
<li>线程安全分析</li>
<li>Monitor</li>
<li>wait/notify</li>
<li>线程状态转换</li>
<li>活跃性</li>
<li>Lock</li>
</ul>
<h4 id="临界区-critical-section"><a class="markdownIt-Anchor" href="#临界区-critical-section">#</a> 临界区 Critical Section</h4>
<ul>
<li>一个程序运行多个线程本身是没有问题的</li>
<li>问题出现在多个线程访问<strong>共享资源</strong>
<ul>
<li>多个线程读<strong>共享资源</strong>其实也没有问题</li>
<li>在多个线程对共享资源读写操作时发生指令交错，就会出现问题</li>
</ul>
</li>
<li>一段代码内如果存在对<strong>共享资源</strong>的多个线程读写操作，就称这段代码为临界区</li>
</ul>
<h4 id="synchronized-解决方案"><a class="markdownIt-Anchor" href="#synchronized-解决方案">#</a> synchronized 解决方案</h4>
<h5 id="应用之互斥"><a class="markdownIt-Anchor" href="#应用之互斥">#</a> <strong>应用之互斥</strong></h5>
<p>为了避免临界区的竞态条件发生，有多种手段可以达到目的</p>
<ul>
<li>阻塞式的解决方案：synchronized、Lock</li>
<li>非阻塞式的解决方案：原子变量</li>
</ul>
<p>本次使用阻塞式的方案：synchronized，来解决上述方案，即俗称的【对象锁】，它采用互斥的方式让同一时刻至多有一个线程能持有【对象锁】</p>
<p>synchronized</p>
<p>语法</p>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">synchronized</span>(对象)&#123; <span class="comment">//线程1， 线程2（blocked）</span></span><br><span class="line">    临界区</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="type">int</span> <span class="variable">counter</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="keyword">static</span> <span class="type">Object</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Objcect</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span>&#123;</span><br><span class="line">    <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span>(lock)&#123;</span><br><span class="line">                counter++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;, <span class="string">&quot;t1&quot;</span>).start();</span><br><span class="line">    </span><br><span class="line">    <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span>(lock)&#123;</span><br><span class="line">                counter--</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;, <span class="string">&quot;t2&quot;</span>).start();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
<h4 id="方法上的synchronized"><a class="markdownIt-Anchor" href="#方法上的synchronized">#</a> 方法上的 synchronized</h4>
<div class="highlight-container" data-rel="Java"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span>&#123;</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">synchronized</span>(<span class="built_in">this</span>)&#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span>&#123;</span><br><span class="line">        </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">synchronized</span>(Test.class)&#123;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
<h4 id="变量的线程安全分析"><a class="markdownIt-Anchor" href="#变量的线程安全分析">#</a> 变量的线程安全分析</h4>
<p>成员变量和静态变量是否是线程安全的？</p>
<ul>
<li>如果他们没有共享，则线程安全</li>
<li>如果他们被共享了，根据他们的状态是否能够改变，又分两种情况
<ul>
<li>如果只有读操作，则线程安全</li>
<li>如果有读写操作，则这段代码是临界区，则需要考虑线程安全</li>
</ul>
</li>
</ul>
<p>局部变量是否是线程安全？</p>
<ul>
<li>局部变量是线程安全的</li>
<li>但局部变量引用的对象则未必
<ul>
<li>如果该对象没有逃离方法的作用范围，他是线程安全的
<ul>
<li>如果该对象逃离方法的作用范围，则需要考虑线程安全</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="常见线程安全类"><a class="markdownIt-Anchor" href="#常见线程安全类">#</a> 常见线程安全类</h3>
<ul>
<li>String</li>
<li>Integer</li>
<li>StringBuffer</li>
<li>Random</li>
<li>Vector</li>
<li>HashTable</li>
<li>java.util.concurrent 的类</li>
</ul>
<p>他们每个类的方法是原子性的</p>
<p>但是多个方法的组合不是原子性的</p>

            </div>

            
                <div class="post-copyright-info">
                    <div class="article-copyright-info-container">
    <ul>
        <li><strong>标题:</strong> JAVA并发编程</li>
        <li><strong>作者:</strong> meteor</li>
        <li><strong>创建于:</strong> 2023-06-05 16:42:26</li>
        
            <li>
                <strong>更新于:</strong> 2023-06-05 00:42:55
            </li>
        
        <li>
            <strong>链接:</strong> https://gitee.com/du-jinliang/2023/06/06/JAVA并发编程/
        </li>
        <li>
            <strong>版权声明:</strong> 本文章采用 <a class="license" target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">CC BY-NC-SA 4.0</a> 进行许可。
        </li>
    </ul>
</div>

                </div>
            

            
                <ul class="post-tags-box">
                    
                        <li class="tag-item">
                            <a href="/tags/java/">#java</a>&nbsp;
                        </li>
                    
                </ul>
            

            

            
                <div class="article-nav">
                    
                        <div class="article-prev">
                            <a class="prev"
                            rel="prev"
                            href="/2023/06/06/Java%E9%A1%B9%E7%9B%AE%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE%E5%8F%8A%E5%B7%A5%E5%85%B7%E7%B1%BB/"
                            >
                                <span class="left arrow-icon flex-center">
                                    <i class="fa-solid fa-chevron-left"></i>
                                </span>
                                <span class="title flex-center">
                                    <span class="post-nav-title-item">Java项目通用配置及工具类</span>
                                    <span class="post-nav-item">上一篇</span>
                                </span>
                            </a>
                        </div>
                    
                    
                        <div class="article-next">
                            <a class="next"
                            rel="next"
                            href="/2023/06/06/Git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/"
                            >
                                <span class="title flex-center">
                                    <span class="post-nav-title-item">Git常用命令</span>
                                    <span class="post-nav-item">下一篇</span>
                                </span>
                                <span class="right arrow-icon flex-center">
                                    <i class="fa-solid fa-chevron-right"></i>
                                </span>
                            </a>
                        </div>
                    
                </div>
            


            
                <div class="comment-container">
                    <div class="comments-container">
    <div id="comment-anchor"></div>
    <div class="comment-area-title">
        <i class="fa-solid fa-comments"></i>&nbsp;评论
    </div>
    

        
            
    <div id="gitalk-container"></div>
    <script data-pjax
            src="//cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.js"></script>
    <script data-pjax>

        function loadGitalk() {
            let __gitalk__pathname = decodeURI(location.pathname);
            const __gitalk__pathnameLength = __gitalk__pathname.length;
            const __gitalk__pathnameMaxLength = 50;
            if (__gitalk__pathnameLength > __gitalk__pathnameMaxLength) {
                __gitalk__pathname = __gitalk__pathname.substring(0, __gitalk__pathnameMaxLength - 3) + '...';
            }

            try {
                Gitalk && new Gitalk({
                    clientID: '55bad54a77b7e60ad62d',
                    clientSecret: '1031c81500c6be06e338087cb7b713f2d0201b46',
                    repo: 'wait-you.github.io',
                    owner: 'wait-you',
                    admin: ['wait-you'],
                    id: 'comment',
                    language: 'zh-CN'
                }).render('gitalk-container');

            } catch (e) {
                window.Gitalk = null;
            }
        }

        if ('true') {
            const loadGitalkTimeout = setTimeout(() => {
                loadGitalk();
                clearTimeout(loadGitalkTimeout);
            }, 1000);
        } else {
            window.addEventListener('DOMContentLoaded', loadGitalk);
        }
    </script>



        
    
</div>

                </div>
            
        </div>

        
            <div class="toc-content-container">
                <div class="post-toc-wrap">
    <div class="post-toc">
        <div class="toc-title">此页目录</div>
        <div class="page-title">JAVA并发编程</div>
        <ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B"><span class="nav-text"> JAVA 并发编程</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E4%B8%8E%E7%BA%BF%E7%A8%8B"><span class="nav-text"> 进程与线程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B"><span class="nav-text"> 进程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B"><span class="nav-text"> 线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BA%8C%E8%80%85%E5%AF%B9%E6%AF%94"><span class="nav-text"> 二者对比</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B9%B6%E8%A1%8C%E4%B8%8E%E5%B9%B6%E5%8F%91"><span class="nav-text"> 并行与并发</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BA%94%E7%94%A8"><span class="nav-text"> 应用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#java%E7%BA%BF%E7%A8%8B"><span class="nav-text"> Java 线程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA%E5%92%8C%E8%BF%90%E8%A1%8C%E7%BA%BF%E7%A8%8B"><span class="nav-text"> 创建和运行线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E8%BF%9B%E7%A8%8B%E7%9A%84%E6%96%B9%E6%B3%95"><span class="nav-text"> 查看进程的方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%BB%E7%BA%BF%E7%A8%8B%E4%B8%8E%E5%AE%88%E6%8A%A4%E7%BA%BF%E7%A8%8B"><span class="nav-text"> 主线程与守护线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BA%94%E7%A7%8D%E7%8A%B6%E6%80%81"><span class="nav-text"> 五种状态</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%AD%E7%A7%8D%E7%8A%B6%E6%80%81"><span class="nav-text"> 六种状态</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B1%E4%BA%AB%E6%A8%A1%E5%9E%8B%E4%B9%8B%E7%AE%A1%E7%A8%8B"><span class="nav-text"> 共享模型之管程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E8%A7%81%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%B1%BB"><span class="nav-text"> 常见线程安全类</span></a></li></ol></li></ol></li></ol>

    </div>
</div>
            </div>
        
    </div>
</div>


                

            </div>
            
            

        </div>

        <div class="main-content-footer">
            <footer class="footer">
    <div class="info-container">
        <div class="copyright-info">
            &copy;
            
              <span>2022</span>
              -
            
            2023&nbsp;&nbsp;<i class="fa-solid fa-heart fa-beat" style="--fa-animation-duration: 0.5s; color: #f54545"></i>&nbsp;&nbsp;<a href="/">meteor</a>
        </div>
        
            <script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="website-count info-item">
                
                    <span id="busuanzi_container_site_uv" class="busuanzi_container_site_uv">
                        访问人数&nbsp;<span id="busuanzi_value_site_uv" class="busuanzi_value_site_uv"></span>
                    </span>
                
                
                    <span id="busuanzi_container_site_pv" class="busuanzi_container_site_pv">
                        总访问量&nbsp;<span id="busuanzi_value_site_pv" class="busuanzi_value_site_pv"></span>
                    </span>
                
            </div>
        
        <div class="theme-info info-item">
            <span class="powered-by-container">由 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1rem" height="1rem" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path fill="#0E83CD" d="M256.4,25.8l-200,115.5L56,371.5l199.6,114.7l200-115.5l0.4-230.2L256.4,25.8z M349,354.6l-18.4,10.7l-18.6-11V275H200v79.6l-18.4,10.7l-18.6-11v-197l18.5-10.6l18.5,10.8V237h112v-79.6l18.5-10.6l18.5,10.8V354.6z"/></svg><a target="_blank" href="https://hexo.io">Hexo</a> 驱动</span>
                <br>
            <span class="theme-version-container">主题&nbsp;<a class="theme-version" target="_blank" href="https://github.com/EvanNotFound/hexo-theme-redefine">Redefine v2.1.4</a>
        </div>
        
            <div class="icp-info info-item"><a target="_blank" rel="nofollow" href="
                
                    beian.miit.gov.cn
                
                ">冀ICP备20010108号</a></div>
        
        
        
            <div id="start_div" style="display:none">
                2022/8/17 11:45:14
            </div>
            <div>
                博客已运行 <span class="odometer" id="runtime_days" ></span> 天 <span class="odometer" id="runtime_hours"></span> 小时 <span class="odometer" id="runtime_minutes"></span> 分钟 <span class="odometer" id="runtime_seconds"></span> 秒
            </div>
        
        
        
            <script async data-pjax>
                try {
                    function odometer_init() {
                    const elements = document.querySelectorAll('.odometer');
                    elements.forEach(el => {
                        new Odometer({
                            el,
                            format: '( ddd).dd',
                            duration: 200
                        });
                    });
                    }
                    odometer_init();
                } catch (error) {}
            </script>
        
        
        
    </div>  
</footer>
        </div>
    </div>

    
        <div class="post-tools">
            <div class="post-tools-container">
    <ul class="article-tools-list">
        <!-- TOC aside toggle -->
        
            <li class="right-bottom-tools page-aside-toggle">
                <i class="fa-regular fa-outdent"></i>
            </li>
        

        <!-- go comment -->
        
            <li class="go-comment">
                <i class="fa-regular fa-comments"></i>
            </li>
        
    </ul>
</div>

        </div>
    

    <div class="right-side-tools-container">
        <div class="side-tools-container">
    <ul class="hidden-tools-list">
        <li class="right-bottom-tools tool-font-adjust-plus flex-center">
            <i class="fa-regular fa-magnifying-glass-plus"></i>
        </li>

        <li class="right-bottom-tools tool-font-adjust-minus flex-center">
            <i class="fa-regular fa-magnifying-glass-minus"></i>
        </li>

        <li class="right-bottom-tools tool-expand-width flex-center">
            <i class="fa-regular fa-expand"></i>
        </li>

        <li class="right-bottom-tools tool-dark-light-toggle flex-center">
            <i class="fa-regular fa-moon"></i>
        </li>

        <!-- rss -->
        

        

        <li class="right-bottom-tools tool-scroll-to-bottom flex-center">
            <i class="fa-regular fa-arrow-down"></i>
        </li>
    </ul>

    <ul class="visible-tools-list">
        <li class="right-bottom-tools toggle-tools-list flex-center">
            <i class="fa-regular fa-cog fa-spin"></i>
        </li>
        
            <li class="right-bottom-tools tool-scroll-to-top flex-center">
                <i class="arrow-up fas fa-arrow-up"></i>
                <span class="percent"></span>
            </li>
        
        
    </ul>
</div>

    </div>

    <div class="image-viewer-container">
    <img src="">
</div>


    


</main>




<script src="/js/utils.js"></script>

<script src="/js/main.js"></script>

<script src="/js/layouts/navbarShrink.js"></script>

<script src="/js/tools/scrollTopBottom.js"></script>

<script src="/js/tools/lightDarkSwitch.js"></script>





    
<script src="/js/tools/codeBlock.js"></script>




    
<script src="/js/layouts/lazyload.js"></script>




    
<script src="/js/tools/runtime.js"></script>

    
<script src="/js/layouts/odometer.min.js"></script>

    
<link rel="stylesheet" href="/assets/odometer-theme-minimal.css">




  
<script src="/js/libs/Typed.min.js"></script>

  
<script src="/js/plugins/typed.js"></script>







<div class="post-scripts pjax">
    
        
<script src="/js/tools/tocToggle.js"></script>

<script src="/js/libs/anime.min.js"></script>

<script src="/js/layouts/toc.js"></script>

<script src="/js/plugins/tabs.js"></script>

    
</div>


    
<script src="/js/libs/pjax.min.js"></script>

<script>
    window.addEventListener('DOMContentLoaded', () => {
        window.pjax = new Pjax({
            selectors: [
                'head title',
                '.page-container',
                '.pjax',
            ],
            history: true,
            debug: false,
            cacheBust: false,
            timeout: 0,
            analytics: false,
            currentUrlFullReload: false,
            scrollRestoration: false,
            // scrollTo: true,
        });

        document.addEventListener('pjax:send', () => {
            Global.utils.pjaxProgressBarStart();
        });

        document.addEventListener('pjax:complete', () => {
            Global.utils.pjaxProgressBarEnd();
            window.pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
            Global.refresh();
        });
    });
</script>




</body>
</html>
